#pragma once
// ==================包含头文件====================
#include "hal/gpio.hpp"
#include "ti_msp_dl_config.h"
#include "hal/delay.hpp"
// ================== 包含头文件 ====================
#include <span>

// ==================随配置变动部分====================
using TOUCH_INT = hal::gpio<GPIOB_BASE,TOUCH_CTP_INT_PIN>;
using TOUCH_RST = hal::gpio<GPIOB_BASE,TOUCH_CTP_RST_PIN>;// 触摸屏复位引脚
using TOUCH_SDA = hal::gpio<GPIOA_BASE,TOUCH_CTP_SDA_PIN>;
using TOUCH_SCL = hal::gpio<GPIOA_BASE,TOUCH_CTP_SCL_PIN>;

// ==================随配置变动部分====================

namespace hal::details_i2c
{
    template <uint32_t I2C_BASE>
    class i2c_config
    {
    public:
        // 获取SPI硬件寄存器指针
        static I2C_Regs* get_base()
        {
            return reinterpret_cast<I2C_Regs*>(I2C_BASE);
        }

        /**
         * @brief 存储器读取操作（带内存地址）硬件i2c
         * @param devAddr 设备地址 (7-bit)
         * @param memAddr 内存地址 (8-bit)
         * @param data 数据接收缓冲区指针
         * @param size 接收数据大小（字节数）
         * @return 操作状态 (true: 成功, false: 失败)
         */
        static uint8_t readMemory(uint8_t devAddr, const uint8_t memAddr, uint8_t* data, size_t size)
        {
            uint8_t params[1];
            params[0]=memAddr;
            // 第一阶段：发送寄存器地址
            DL_I2C_fillControllerTXFIFO(get_base(), params, 1);  // 发送完整地址
            DL_I2C_flushControllerTXFIFO(get_base());  // 确保FIFO清空

            DL_I2C_startControllerTransfer(get_base(), devAddr,
                                            DL_I2C_CONTROLLER_DIRECTION_TX, 1);  // 发送2字节地址

            while (!(DL_I2C_getControllerStatus(get_base()) & DL_I2C_CONTROLLER_STATUS_IDLE)) {}

            // 错误检测（关键修复）
            if (DL_I2C_getControllerStatus(get_base()) & (DL_I2C_CONTROLLER_STATUS_ERROR |
                                                       DL_I2C_CONTROLLER_STATUS_ARBITRATION_LOST)) {
                DL_I2C_resetControllerTransfer(get_base());  // 重置控制器
                return false;
                                                       }

            // 第二阶段：读取数据
            DL_I2C_startControllerTransfer(get_base(), devAddr,
                                            DL_I2C_CONTROLLER_DIRECTION_RX, size);

            // 带超时的数据读取
            for (size_t i = 0; i < size; i++) {
                while (DL_I2C_isControllerRXFIFOEmpty(get_base())) {
                    // 检查总线错误
                    if (DL_I2C_getControllerStatus(get_base()) & DL_I2C_CONTROLLER_STATUS_ERROR) {
                        DL_I2C_resetControllerTransfer(get_base());
                        return false;
                    }
                }
                data[i] = DL_I2C_receiveControllerData(get_base());
            }
            return true;
        }


    };
    class i2c_config_soft
    {
    public:
        static  void SDA_IN()
        {
            TOUCH_SDA::setInput();
        }

        static  void SDA_OUT()
        {
            TOUCH_SDA::setOutput();
        }

        static  void Start()
        {
            SDA_OUT();
            TOUCH_SDA::high();
            TOUCH_SCL::high();
            delay::us(4);
            TOUCH_SDA::low();
            delay::us(4);
            TOUCH_SCL::low();
        }

        static  void Stop()
        {
            SDA_OUT();
            TOUCH_SCL::low();
            TOUCH_SDA::low();
            delay::us(4);
            TOUCH_SCL::high();
            delay::us(4);
            TOUCH_SDA::high();
        }

        static unsigned char Wait_Ack()
        {
            unsigned char ucErrTime=0;
            SDA_IN();
            TOUCH_SDA::high();
            delay::us(1);
            TOUCH_SCL::high();
            delay::us(1);
            while(TOUCH_SDA::read())
            {
                ucErrTime++;
                if(ucErrTime>250)
                {
                    Stop();
                    return 1;
                }
            }
            TOUCH_SCL::low();
            return 0;
        }

        static void Ack()
        {
            TOUCH_SCL::low();
            SDA_OUT();
            TOUCH_SDA::low();
            delay::us(2);
            TOUCH_SCL::high();
            delay::us(2);
            TOUCH_SCL::low();
        }
        static void NAck()
        {
            TOUCH_SCL::low();
            SDA_OUT();
            TOUCH_SDA::high();
            delay::us(2);
            TOUCH_SCL::high();
            delay::us(2);
            TOUCH_SCL::low();
        }

        static void Send_Byte(unsigned char txd)
        {
            SDA_OUT();
            TOUCH_SCL::low();
            for(unsigned char t = 0;t<8;t++)
            {
                TOUCH_SDA::write((txd&0x80)>>7);
                txd<<=1;
                delay::us(2);
                TOUCH_SCL::high();
                delay::us(2);
                TOUCH_SCL::low();
                delay::us(2);
            }
        }

        static unsigned char Read_Byte(const unsigned char ack)
        {
            unsigned char receive=0;
            SDA_IN();
            for(unsigned char i = 0;i<8;i++ )
            {
                TOUCH_SCL::low();
                delay::us(2);
                TOUCH_SCL::high();
                receive<<=1;
                if(TOUCH_SDA::read())receive++;
                delay::us(1);
            }
            if (!ack)
                NAck();
            else
                Ack();
            return receive;
        }
    };
}

namespace hal
{
    // 实例化I2C
    using i2c0 = details_i2c::i2c_config<I2C0_BASE>;
    using i2c1 = details_i2c::i2c_config<I2C1_BASE>;
}
